package com.zx.idc.backend.gui.api.commom.base;

import com.zx.idc.backend.gui.api.commom.factory.CompressionProvider;
import com.zx.idc.backend.gui.api.commom.factory.EncryptProvider;
import com.zx.idc.backend.gui.api.commom.factory.HashProvider;
import com.zx.idc.common.attributes.SchemaFileNameAttributes;
import com.zx.idc.common.attributes.SystemAttributes;
import com.zx.idc.common.lang.DateUtil;
import com.zx.idc.common.lang.StringUtil;
import com.zx.idc.common.spring.SpringConfigUtil;
import com.zx.idc.common.util.CRC64;
import com.zx.idc.common.util.LocalDateTimeFormatUtil;
import com.zx.idc.xml.utils.JaxbUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.time.LocalDate;
import java.util.Date;

import static com.zx.idc.common.attributes.SystemAttributes.IDC_HOME;
import static com.zx.idc.common.attributes.SystemAttributes.UPLOAD_FILE_SUFFIX;

/**
 * Created by hasee on 2019/2/22.
 */
public class BaseIDCCommand {
    protected static final Logger LOG = LoggerFactory.getLogger(BaseIDCCommand.class);

    /**
     * 身份认证
     *
     * @param hashAlgorithm hash算法类型
     * @param randVal       随机符串
     * @param password      用户口令
     * @param pwdHash       对方hash后的结果
     * @return 结果，认证通过返回true
     */
    protected boolean authentication(int hashAlgorithm, String randVal, String password, String pwdHash) {
        return hashVerifyWithoutPassword(hashAlgorithm, stitching(password, randVal), pwdHash);
    }

    /**
     * 字符串拼接
     *
     * @param strStart 用户口令
     * @param strEnd   随机符串
     * @return 拼接后的hashSting
     */
    protected String stitching(String strStart, String strEnd) {
        return new StringBuilder()
                .append(strStart)
                .append(strEnd)
                .toString();
    }

    /**
     * hash验证方法
     *
     * @param hashAlgorithm hash算法类型
     * @param text          源数据
     * @param digestVal       hash后的结果
     * @param digestPassword 签名秘钥
     * @return 相同为true
     */
    protected final boolean hashVerify(int hashAlgorithm, String text, String digestVal, String digestPassword) {
        return HashProvider.verifyByBase64(hashAlgorithm, text, digestVal, digestPassword);
    }

    protected final boolean hashVerify(int hashAlgorithm, byte[] bytes, String hashVal, String digestPassword) {
        return HashProvider.verifyByBase64(hashAlgorithm, bytes, hashVal, digestPassword);
    }

    /**
     * hash验证方法, 无需签名秘钥
     *
     * @param hashAlgorithm hash算法类型
     * @param text          源数据
     * @param hashVal       hash后的结果
     * @return 相同为true
     */
    protected final boolean hashVerifyWithoutPassword(int hashAlgorithm, String text, String hashVal) {
        return HashProvider.verifyByBase64WithoutPassword(hashAlgorithm, text, hashVal);
    }

    protected final boolean hashVerifyWithoutPassword(int hashAlgorithm, byte[] bytes, String hashVal) {
        return HashProvider.verifyByBase64WithoutPassword(hashAlgorithm, bytes, hashVal);
    }


    //单向解密

    /**
     * 单向解密
     *
     * @param encryptAlgorithm 解密算法的类型
     * @param val              机密后的数据
     * @param key              秘钥
     * @return 源数据，解密失败为空
     */
    protected final byte[] decodeAsBytes(int encryptAlgorithm, String val, String key, String offset) {
        return EncryptProvider.decryptAsBytes(encryptAlgorithm, val, key, offset);
    }

    /**
     * 解压
     *
     * @param compressionFormat 解压类型
     * @param text              压缩的内容
     * @return 解压后的内容
     */
    protected final String deCmp(int compressionFormat, byte[] text) {
        return CompressionProvider.deCMP(compressionFormat, text);
    }

    /**
     * 压缩
     *
     * @param compressionFormat 压缩类型
     * @param text              要压缩的文本
     * @return 压缩后的内容
     */
    protected final byte[] enCmp(int compressionFormat, String text) {
        return CompressionProvider.enCMP(compressionFormat, text);
    }

    /**
     * xml转为实体
     *
     * @param str        xml数据
     * @param clazz      xml对应的实体
     * @param schemaPath schema文件路径
     * @param <T>        xml对应的实体
     * @return xml相应的实体，不匹配返回空
     */
    protected final <T> T xml2Bean(String str, Class<T> clazz, String schemaPath) {
        try {
            return JaxbUtils.xmlToBean(str, clazz, schemaPath);
        } catch (Exception e) {
            LOG.debug(e.getMessage(), e);
            return null;
        }
    }

    /**
     * 随机生成字符串
     *
     * @param num 生成的长度
     * @return
     */
    protected final String randomString(int num) {
        return StringUtil.generatorRandomString(num);
    }

    /**
     * 单向加密
     *
     * @param encryptAlgorithm 加密算法的类型
     * @param val              要加密的内容
     * @param key              秘钥
     * @return
     */
//    protected final String encode(int encryptAlgorithm, String val, String key) {
//        return EncryptProvider.encode(encryptAlgorithm, val, key);
//    }
    protected final String encode(int encryptAlgorithm, byte[] val, String key, String offset) {
        return EncryptProvider.encrypt(encryptAlgorithm, val, key, offset);
    }

//    protected final String encode(int encryptAlgorithm, byte[] val, String key) {
//        return EncryptProvider.encode(encryptAlgorithm, val, key);
//    }

    /**
     * 获取yml配置的内容
     *
     * @param key yml的key
     * @return yml的值
     */
    public static String getConfig(String key) {
        return SpringConfigUtil.get(key);
    }

    /**
     * 获取yml配置的内容
     *
     * @param key yml的key
     * @return yml的值
     */
    public static Integer getConfigInt(String key) {
        return SpringConfigUtil.get(key, Integer.class);
    }

    /**
     * 获取完整的schema文件路径
     *
     * @param fileName
     * @return
     */
    public static String getSchemaFilePath(String fileName) {
        StringBuilder sb = new StringBuilder();
        return sb.append(SpringConfigUtil.get(SystemAttributes.WEB_SERVICE_SCHEMA_PATH))
                .append(fileName)
                .append(SchemaFileNameAttributes.SCHEMA_FILE_SUFFIX)
                .toString();
    }

    /**
     * bean根据schema文件验证转为String
     *
     * @param t          对象
     * @param schemaPath schema路径
     * @param <T>
     * @return 转换后的String字符串，失败则为空
     */
    public static <T> String bean2xmlStr(T t, String schemaPath) {
        return JaxbUtils.beanToXml(t, schemaPath);
    }

    /**
     * hash后进行BASE64编码
     *
     * @param type
     * @param text
     * @return
     */
    public static String hashByBase64(int type, String text) {
        return HashProvider.hashByBase64(type, text);
    }

    public static String hashByBase64(int type, byte[] text) {
        return HashProvider.hashByBase64(type, text);
    }

    /**
     * 获取上传文件路径
     *
     * @param type 上传文件的类型
     * @return 上传文件的路径
     */
    public static String getUploadPath(String type) {
        String currentTimeTag = DateUtil.formatDate(new Date(), "yyyyMMddHHmmss");
        long filenameSign = Math.abs(CRC64.crc64Long(String.format("%d_%s.xml", System.nanoTime(), type)));
        String filename = new StringBuilder(currentTimeTag).append(filenameSign).append(UPLOAD_FILE_SUFFIX).toString();
        LOG.debug("upload file name as： {}， datatype as: {}", filename, type);
        return new StringBuilder()
                .append(getConfig(IDC_HOME))
                .append("/")
                .append(type)
            .append("/")
            .append(LocalDateTimeFormatUtil.LocalDate2yyyyMMdd(LocalDate.now()))
                .append("/")
            .append(filename)
                .toString();
    }

}
